#include <Kharlia/Engine/Common.h>
#include <Kharlia/Engine/Resource.h>
#include <Kharlia/Engine/Init.h>
#include <Kharlia/Engine/Engine.h>
#include <Kharlia/Engine/Client.h>

#include <CEGUIRenderer.h>

namespace kharlia { namespace engine {

void FResourceManager::RegisterResource(shared_ptr<FResource> res) {
    if (!res->mManager.expired()) {
        format msg("resource already registered with a manager: %1%");
        msg % extract<const char*>(res->GetName());
        throw RuntimeError(msg);
    }
    if (mResources.find(res->GetName()) != mResources.end()) {
        format msg("resource already registered with name: %1%");
        msg % extract<const char*>(res->GetName());
        throw RuntimeError(msg);
    }
    mResources.insert(ResourcesType::value_type(res->GetName(), res));
    mGroups.insert(res->GetGroup());
    res->mManager = shared_from_this();
}

void FResourceManager::UnregisterResource(shared_ptr<FResource> res) {
    assert(!res->mManager.expired());
    assert(res->mManager.lock().get() == this);
    if (mResources.erase(res->GetName()) != 1) {
        throw RuntimeError("attempting to unregister unknown resource");
    }
    res->mManager.reset();
}

void FResourceManager::UnloadResources() {
    ResourcesType::iterator it;
    for (it = mResources.begin(); it != mResources.end(); it++) {
        shared_ptr<FResource> r = it->second;
        if (r->GetState() != RS_UNLOADED) {
            r->Unload();
            assert(r->GetState() == RS_UNLOADED);
        }
    }
}

void FResourceManager::UnloadResources(str groupName) {
    ResourcesType::iterator it;
    for (it = mResources.begin(); it != mResources.end(); it++) {
        shared_ptr<FResource> r = it->second;
        if (r->GetState() != RS_UNLOADED && r->GetGroup() == groupName) {
            r->Unload();
            assert(r->GetState() == RS_UNLOADED);
        }
    }
}

void FResourceManager::UnregisterResources() {
    mResources.clear();
}

FResource::FResource(str name, str group):
    mManager(), mName(name), mGroup(group), mState(RS_UNLOADED)
{
}

FResource::~FResource() {
}

FTexture::FTexture(str name, str group, ui::Texture* tex, shared_ptr<CClient> cl):
    FResource(name, group), mIntTexture(tex), mClient(cl)
{
    if (tex) {
        assert(cl);
        mState = RS_LOADED;
    }
}

FTexture::~FTexture() {
    DestroyIntTexture();
}

void FTexture::DestroyIntTexture() {
    if (mIntTexture) {
        assert(mClient);
        mState = RS_UNLOADING;
        ui::Renderer* rn = mClient->GetUiRenderer();
        if (rn)
            rn->destroyTexture(*mIntTexture);
        mClient.reset();
        mIntTexture = NULL;
        mState = RS_UNLOADED;
    }
}

void _InitResourceClasses() {
    _InitResourceBindings();
}


}}